package com.example.result.kotlin.base

import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe

class InterviewTest : StringSpec({
    "面试3" {
//        val input = arrayOf("file1a.gif", "file01.gif")
        val input = arrayOf("file01.gif", "file1a.gif")
        val output = arrayOf("file01.gif", "file1a.gif")
        Solution.sort(input) shouldBe output
    }

    "面试" {
        val input = arrayOf(
            "file2.gif",
            "file01.gif",
            "1file.jpg",
            "1file.gif",
            "file10.gif",
            "file1.gif",
            "file1a.gif"
        )
        val output = arrayOf(
            "1file.gif",
            "1file.jpg",
            "file1.gif",
            "file01.gif",
            "file1a.gif",
            "file2.gif",
            "file10.gif"
        )
        Solution.sort(input) shouldBe output
    }
    "面试2" {
        val input = arrayOf("1file.png", "file10.gif", "file2.gif")
        val output = arrayOf("1file.png", "file2.gif", "file10.gif")
        Solution.sort(input) shouldBe output
    }
})

object Solution {
    fun sort(fileNames: Array<String>): Array<String> {
        return fileNames.map { FileSortInfo(it) }
            .sortedWith { a, b -> a.sort(b) }
            .map { it.filename }
            .toTypedArray()
    }
}

class FileSortInfo(val filename: String) {
    val data = mutableListOf<Part>()

    init {
        val last = StringBuilder()
        var isNum = false
        for (c in filename) {
            if (c.isDigit()) {
                if (last.isNotEmpty() && !isNum) {
                    data.add(Part.Str(last.toString()))
                    last.clear()
                }
                last.append(c)
                isNum = true
            } else {
                if (last.isNotEmpty() && isNum) {
                    val s = last.toString()
                    data.add(Part.Num(s.toInt()))
                    last.clear()
                }
                last.append(c)
                isNum = false
            }
        }
        if (last.isNotEmpty()) {
            val s = last.toString()
            if (isNum) {
                data.add(Part.Num(s.toInt()))
            } else {
                data.add(Part.Str(s))
            }
            last.clear()
        }
//        println("$filename:$data")
    }

    /**相同索引的Part先比较，
     * 如果全部相等，谁的Part数量多谁大，
     * 如果相等，谁的字符数长谁大*/
    fun sort(other: FileSortInfo): Int {
        for (i in 0..<minOf(data.size, other.data.size)) {
            val ans = data[i].sort(other.data[i])
            if (ans != 0) {
                return ans
            }
        }
        val ans = data.size.compareTo(other.data.size)
        if (ans != 0) {
            return ans
        }
        return filename.length.compareTo(other.filename.length)
    }
}


sealed class Part {
    data class Num(val v: Int) : Part() {
        override fun sort(right: Part): Int {
            if (right is Num) {
                return v.compareTo(right.v)
            }
            return -1
        }
    }

    data class Str(val v: String) : Part() {
        override fun sort(right: Part): Int {
            if (right is Str) {
                return v.compareTo(right.v)
            }
            return 1
        }
    }


    /**1.  Str > Num
     * 2. Num.v == Num.v
     * */
    abstract fun sort(right: Part): Int
}
